The following tutorial shows the basics of setting up and interacting with an ArchR Project using a gold-standard downsampled dataset of hematopoietic cells Granja* et al. Nature Biotechnology 2019. This tutorial and all of the accompanying vignettes assume that you are running ArchR locally. Once all of these steps work for you, feel free to set up ArchR to work in a cluster environment. This tutorial does not explain every detail of every step. Please see the Vignettes section for more details on each major analytical step and all of the major features of ArchR.

1 What is an ArrowFile / ArchRProject?

The base unit of an analytical project in ArchR is called an ArrowFile. Each ArrowFile, stores all of the data associated with an individual sample (i.e. metadata, accessible fragments and data matrices). Here, a sample would be the most detailed unit of analysis desired (for ex. a single replicate of a particular condition). During creation and as additional analyses are performed, ArchR updates and edits each ArrowFile to contain additional layers of information. Then, an ArchRProject allows you to associate these ArrowFiles together into a single analytical framework.

Certain actions can be taken directly on ArrowFiles while other actions are taken on an ArchRProject which in turn updates each associated ArrowFile. Because ArrowFiles are stored as large HDF5-format files, “get-er” functions in ArchR retrieve data by interacting with the ArchRProject.

3 Creating Arrow Files

For this tutorial, we will download a collection of fragment files. Fragment files are one of the base file types of the 10x Genomics analytical platform (and others) and can be easily created from any bam file. See the ArchR input types vignette for information on making your own fragment files. Once we have our fragment files, we provide their names as a character vector to createArrowFiles. During creation, some basic matrices and data is added to each ArrowFile including a TileMatrix containing insertion counts across genome-wide 500-bp bins (see addTileMatrix) and a GeneScoreMatrix that is determined based on weighting insertion counts in tiles nearby a gene promoter (see addGeneScoreMatrix).

4 Tidying up our data and creating an ArchRProject

One major source of trouble in single-cell data is the contribution of “doublets” to the analysis. A doublet refers to a single droplet that received a single barcoded bead and more than one nucleus. This causes the reads from more than one cell to appear as a single cell. We remove these computationally and describe this doublet removal process in more depth in the doublet removal vignette.

5 Dimensionality Reduction

At this point, we have an ArchR project that is ready to be used in downstream visualizations and analyses. The first thing we will do is use an iterative latent semantic indexing (LSI) approach to define clusters in our data. Once we have identified clusters in our data, we can plot a UMAP embedding. For more details, see the dimensionality reduction vignette.


5.1 UMAP w/ Clusters

This plot shows gene experimental samples and clusters described above overlayed onto the UMAP embedding. (Note if you see a blank space below try firefox or safari)

6 Identifying Cluster Cell Types Using Marker Genes

In order to understand which clusters correspond to which cell types, we use a supervised approach based on prior knowledge of the genes that are active in specific cell types. We determine gene activity scores for each putative marker gene based on chromatin accessibility signal in the region surrounding the gene’s promoter. We can then overlay these gene activity scores on our UMAP embedding to visualize the relationship between gene activity and cluster. For more details, see the marker genes vignette.


6.1 UMAP GeneScores

This plot shows gene activity scores of the marker genes described above overlayed onto the UMAP embedding. The gene scores are imputed using Magic when running addImupteWeights. (Note if you see a blank space below try firefox or safari)

6.2 Track-Plots



6.3 Marker GeneScores Heatmap



7 Creating a Reproducible Peak Set

One of the most complicated aspects about ATAC-seq and scATAC-seq analysis is the generation of a reproducible and robust peak set. In ArchR, we use an iterative overlap removal process that we first described in Corces* & Granja* et al. Science 2018. This process is described in detail in the peak calling vignette.

To robustly call peaks, we first merge the sparse single-cell data into pseudo-bulk replicates by aggregating the insertions from many individual cells into a single group. We make multiple pseudo-bulk replicates for each cluster to enable an assessment of peak reproducibility. This process of pseudo-bulk generation is described in detail in the pseudo-bulk generation vignette. We than call peaks using MACS2 and perform our iterative overlap removal. Once we obtain a finalized peak set, we collect insertion counts in each peak for each single cell and associate this with the corresponding ArrowFile via the ArchRProject.

8 Identifying Marker Peaks

Often times, we are interested to know which peaks are unique to an individual cluster or a small group of clusters. We can do this in an unsupervised fashion in ArchR:

Using our tutorial data, your marker peak heatmap should look like this.

9 Performing Motif Enrichments

QQQQQQQ - I think the concept of TF deviations is still abstract to most people. Does ArchR do motif enrichment with hypergeometric test as well??

Using the reproducible peak set that we defined above, we can use ArchR to calculate TF deviations on a single-cell basis for transcription factors in the peaks identified in each cluster. We can then overlay these deviations on on UMAP embedding. This effectively infers differences in TF activity across all single cells and is very useful in identifying regulatory factors governing cell fate.

Using our tutorial data, your marker peak heatmap should look like this.

10 Performing TF Footprinting

Transcription factor footprinting can also be done in ArchR with a single command. We note that the footprints generated by the tutorial data are not as clean as would be desired but this is because of the small size of the tutorial dataset.

LS0tCnRpdGxlOiAiR2V0dGluZyBTdGFydGVkIFdpdGggQXJjaFIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlICMgdGFibGUgb2YgY29udGVudCB0cnVlCiAgICB0b2NfZGVwdGg6IDMgICMgdXB0byB0aHJlZSBkZXB0aHMgb2YgaGVhZGluZ3MgKHNwZWNpZmllZCBieSAjLCAjIyBhbmQgIyMjKQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlICAjIyBpZiB5b3Ugd2FudCBudW1iZXIgc2VjdGlvbnMgYXQgZWFjaCB0YWJsZSBoZWFkZXIKICAgICN0aGVtZTogY29zbW8gICMgbWFueSBvcHRpb25zIGZvciB0aGVtZSwgdGhpcyBvbmUgaXMgbXkgZmF2b3JpdGUuCiAgICBoaWdobGlnaHQ6IHRhbmdvICAjIHNwZWNpZmllcyB0aGUgc3ludGF4IGhpZ2hsaWdodGluZyBzdHlsZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKCmBgYHtyIGltYWdlLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygKICBjKAogICAgIi4uLy4uL2ltYWdlcy9BcmNoUlByb2plY3RfU2NoZW1hdGljLnBuZyIsIAogICAgIi4uLy4uL2ltYWdlcy9BcmNoUl9GdW5jdGlvblNjaGVtYXRpYy5wbmciLCAKICAgICIuLi8uLi9pbWFnZXMvdHV0b3JpYWxfMV9VTUFQLUNsdXN0ZXJzLnBkZiIsIAogICAgIi4uLy4uL2ltYWdlcy90dXRvcmlhbF8yX3RyYWNrcy5wZGYiLCAKICAgICIuLi8uLi9pbWFnZXMvdHV0b3JpYWxfM19NYXJrZXJHZW5lU2NvcmVzLnBkZiIsIAogICAgIi4uLy4uL2ltYWdlcy90dXRvcmlhbF80X01hcmtlckdlbmVIZWF0bWFwLnBkZiIKICAgICkKICApCmBgYAoKVGhlIGZvbGxvd2luZyB0dXRvcmlhbCBzaG93cyB0aGUgYmFzaWNzIG9mIHNldHRpbmcgdXAgYW5kIGludGVyYWN0aW5nIHdpdGggYW4gQXJjaFIgUHJvamVjdCB1c2luZyBhIGdvbGQtc3RhbmRhcmQgZG93bnNhbXBsZWQgZGF0YXNldCBvZiBoZW1hdG9wb2lldGljIGNlbGxzIFtHcmFuamEqIGV0IGFsLiBOYXR1cmUgQmlvdGVjaG5vbG9neSAyMDE5XShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8zMTc5MjQxMSkuIFRoaXMgdHV0b3JpYWwgYW5kIGFsbCBvZiB0aGUgYWNjb21wYW55aW5nIHZpZ25ldHRlcyBhc3N1bWUgdGhhdCB5b3UgYXJlIHJ1bm5pbmcgQXJjaFIgX19sb2NhbGx5X18uIE9uY2UgYWxsIG9mIHRoZXNlIHN0ZXBzIHdvcmsgZm9yIHlvdSwgZmVlbCBmcmVlIHRvIFtzZXQgdXAgQXJjaFIgdG8gd29yayBpbiBhIGNsdXN0ZXIgZW52aXJvbm1lbnRdKGFydGljbGVzL0FydGljbGVzL2NsdXN0ZXJDb21wdXRpbmcuaHRtbCkuIFRoaXMgdHV0b3JpYWwgZG9lcyBub3QgZXhwbGFpbiBldmVyeSBkZXRhaWwgb2YgZXZlcnkgc3RlcC4gUGxlYXNlIHNlZSB0aGUgW1ZpZ25ldHRlcyBzZWN0aW9uXShhcnRpY2xlcy9pbmRleC5odG1sKSBmb3IgbW9yZSBkZXRhaWxzIG9uIGVhY2ggbWFqb3IgYW5hbHl0aWNhbCBzdGVwIGFuZCBhbGwgb2YgdGhlIG1ham9yIGZlYXR1cmVzIG9mIEFyY2hSLgoKIyBXaGF0IGlzIGFuIGBBcnJvd0ZpbGVgIC8gYEFyY2hSUHJvamVjdGA/CgpUaGUgYmFzZSB1bml0IG9mIGFuIGFuYWx5dGljYWwgcHJvamVjdCBpbiBBcmNoUiBpcyBjYWxsZWQgYW4gYEFycm93RmlsZWAuIEVhY2ggYEFycm93RmlsZWAsIHN0b3JlcyBhbGwgb2YgdGhlIGRhdGEgYXNzb2NpYXRlZCB3aXRoIGFuIGluZGl2aWR1YWwgc2FtcGxlIChpLmUuIG1ldGFkYXRhLCBhY2Nlc3NpYmxlIGZyYWdtZW50cyBhbmQgZGF0YSBtYXRyaWNlcykuIEhlcmUsIGEgc2FtcGxlIHdvdWxkIGJlIHRoZSBtb3N0IGRldGFpbGVkIHVuaXQgb2YgYW5hbHlzaXMgZGVzaXJlZCAoZm9yIGV4LiBhIHNpbmdsZSByZXBsaWNhdGUgb2YgYSBwYXJ0aWN1bGFyIGNvbmRpdGlvbikuIER1cmluZyBjcmVhdGlvbiBhbmQgYXMgYWRkaXRpb25hbCBhbmFseXNlcyBhcmUgcGVyZm9ybWVkLCBBcmNoUiB1cGRhdGVzIGFuZCBlZGl0cyBlYWNoIGBBcnJvd0ZpbGVgIHRvIGNvbnRhaW4gYWRkaXRpb25hbCBsYXllcnMgb2YgaW5mb3JtYXRpb24uClRoZW4sIGFuIGBBcmNoUlByb2plY3RgIGFsbG93cyB5b3UgdG8gYXNzb2NpYXRlIHRoZXNlIGBBcnJvd0ZpbGVzYCB0b2dldGhlciBpbnRvIGEgc2luZ2xlIGFuYWx5dGljYWwgZnJhbWV3b3JrLgoKIVtdKC4uLy4uL2ltYWdlcy9BcmNoUlByb2plY3RfU2NoZW1hdGljLnBuZyl7d2lkdGg9NzAwcHh9CgpDZXJ0YWluIGFjdGlvbnMgY2FuIGJlIHRha2VuIGRpcmVjdGx5IG9uIGBBcnJvd0ZpbGVzYCB3aGlsZSBvdGhlciBhY3Rpb25zIGFyZSB0YWtlbiBvbiBhbiBgQXJjaFJQcm9qZWN0YCB3aGljaCBpbiB0dXJuIHVwZGF0ZXMgZWFjaCBhc3NvY2lhdGVkIGBBcnJvd0ZpbGVgLiBCZWNhdXNlIGBBcnJvd0ZpbGVzYCBhcmUgc3RvcmVkIGFzIGxhcmdlIEhERjUtZm9ybWF0IGZpbGVzLCAiZ2V0LWVyIiBmdW5jdGlvbnMgaW4gQXJjaFIgcmV0cmlldmUgZGF0YSBieSBpbnRlcmFjdGluZyB3aXRoIHRoZSBgQXJjaFJQcm9qZWN0YC4KCiFbXSguLi8uLi9pbWFnZXMvQXJjaFJfRnVuY3Rpb25TY2hlbWF0aWMucG5nKXt3aWR0aD00MDBweH0KCiMgR2V0dGluZyBTZXQgVXAKClRoZSBmaXJzdCB0aGluZyB3ZSBkbyBpcyBzZXQgdXAgb3VyIHdvcmtpbmcgZGlyZWN0b3J5LCBsb2FkIG91ciBnZW5vbWUgYW5ub3RhdGlvbnMsIGFuZCBzZXQgdGhlIG51bWJlciBvZiB0aHJlYWRzIHdlIHdvdWxkIGxpa2UgdG8gdXNlLiBEZXBlbmRpbmcgb24gdGhlIGNvbmZpZ3VyYXRpb24gb2YgeW91ciBsb2NhbCBlbnZpcm9ubWVudCwgeW91IG1heSBuZWVkIHRvIG1vZGlmeSB0aGUgbnVtYmVyIG9mIGB0aHJlYWRzYCB1c2VkIGJlbG93IGluIGBhZGRBcmNoUlRocmVhZHNgLgoKYGBge3IgZXZhbD1GQUxTRX0KI0xvYWQgUiBMaWJyYXJpZXMKbGlicmFyeShBcmNoUikKCiNTZXQvQ3JlYXRlIFdvcmtpbmcgRGlyZWN0b3J5IHRvIEZvbGRlciBmb3IgQW5hbHlzaXMKd2QgPC0gIi9Wb2x1bWVzL0pHX1NTRF8yL0RhdGEvQW5hbHlzaXMvVHV0b3JpYWwvSGVtZV9UdXRvcmlhbDMiCmRpci5jcmVhdGUod2QsIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQpzZXR3ZCh3ZCkKCiNMb2FkIEdlbm9tZSBBbm5vdGF0aW9ucy4gQXZhaWxhYmxlIGFubm90YXRpb25zIGFyZSBmb3IgSGcxOSwgSGczOCwgTW05LCBvciBNbTEwLiAKIyhOb3RlIGlmIHlvdSB3YW50IHRvIGJ1aWxkIGEgY3VzdG9tIGFubm90YXRpb24gc2VlIGNyZWF0ZUdlbmVBbm5vdGF0aW9uIG9yIGNyZWF0ZUdlbm9tZUFubm90YXRpb24pLgpkYXRhKCJnZW5lQW5ub0hnMTkiKQpkYXRhKCJnZW5vbWVBbm5vSGcxOSIpCmdlbmVBbm5vIDwtIGdlbmVBbm5vSGcxOQpnZW5vbWVBbm5vIDwtIGdlbm9tZUFubm9IZzE5CgojU2V0IERlZmF1bHQgVGhyZWFkcyBmb3IgQXJjaFIgRnVuY3Rpb25zCiNCeSBkZWZhdWx0IEFyY2hSIHVzZXMgdGhlIHRvdGFsIG51bWJlciBvZiBjb3JlcyBhdmFpbGFibGUgLyAyLiBJZiB3aW5kb3dzIHRoaXMgd2lsbCBiZSBzZXQgdG8gMS4KYWRkQXJjaFJUaHJlYWRzKCkKYGBgCgojIENyZWF0aW5nIEFycm93IEZpbGVzCgpGb3IgdGhpcyB0dXRvcmlhbCwgd2Ugd2lsbCBkb3dubG9hZCBhIGNvbGxlY3Rpb24gb2YgZnJhZ21lbnQgZmlsZXMuIEZyYWdtZW50IGZpbGVzIGFyZSBvbmUgb2YgdGhlIGJhc2UgZmlsZSB0eXBlcyBvZiB0aGUgMTB4IEdlbm9taWNzIGFuYWx5dGljYWwgcGxhdGZvcm0gKGFuZCBvdGhlcnMpIGFuZCBjYW4gYmUgZWFzaWx5IGNyZWF0ZWQgZnJvbSBhbnkgYmFtIGZpbGUuIFNlZSBbdGhlIEFyY2hSIGlucHV0IHR5cGVzIHZpZ25ldHRlXShhcnRpY2xlcy9BcnRpY2xlcy9pbnB1dEZpbGVzLmh0bWwpIGZvciBpbmZvcm1hdGlvbiBvbiBtYWtpbmcgeW91ciBvd24gZnJhZ21lbnQgZmlsZXMuIE9uY2Ugd2UgaGF2ZSBvdXIgZnJhZ21lbnQgZmlsZXMsIHdlIHByb3ZpZGUgdGhlaXIgbmFtZXMgYXMgYSBjaGFyYWN0ZXIgdmVjdG9yIHRvIGBjcmVhdGVBcnJvd0ZpbGVzYC4gRHVyaW5nIGNyZWF0aW9uLCBzb21lIGJhc2ljIG1hdHJpY2VzIGFuZCBkYXRhIGlzIGFkZGVkIHRvIGVhY2ggYEFycm93RmlsZWAgaW5jbHVkaW5nIGEgYFRpbGVNYXRyaXhgIGNvbnRhaW5pbmcgaW5zZXJ0aW9uIGNvdW50cyBhY3Jvc3MgZ2Vub21lLXdpZGUgNTAwLWJwIGJpbnMgKHNlZSBgYWRkVGlsZU1hdHJpeGApIGFuZCBhIGBHZW5lU2NvcmVNYXRyaXhgIHRoYXQgaXMgZGV0ZXJtaW5lZCBiYXNlZCBvbiB3ZWlnaHRpbmcgaW5zZXJ0aW9uIGNvdW50cyBpbiB0aWxlcyBuZWFyYnkgYSBnZW5lIHByb21vdGVyIChzZWUgYGFkZEdlbmVTY29yZU1hdHJpeGApLgoKYGBge3IgZXZhbD1GQUxTRX0KI0dldCBUdXRvcmlhbCBEYXRhIH4yLjJHQiBUbyBEb3dubG9hZCAoaWYgZG93bmxvYWRlZCBhbHJlYWR5IEFyY2hSIHdpbGwgYnlwYXNzIGRvd25sb2FkaW5nKS4KaW5wdXRGaWxlcyA8LSBnZXRUdXRvcmlhbERhdGEoIkhlbWF0b3BvaWVzaXMiKQoKI0NyZWF0ZSBBcnJvdyBGaWxlcyAofjEwLTE1IG1pbnV0ZXMpIHcvIGhlbHBmdWwgbWVzc2FnZXMgZGlzcGxheWluZyBwcm9ncmVzcy4KI1RoaXMgc3RlcCB3aWxsIGZvciBlYWNoIHNhbXBsZSA6CiMgMS4gUmVhZCBBY2Nlc3NpYmxlIEZyYWdtZW50cy4KIyAyLiBJZGVudGlmeSBDZWxscyBRQyBJbmZvcm1hdGlvbiAoVFNTIEVucmljaG1lbnQsIE51Y2xlb3NvbWUgaW5mbykuCiMgMy4gRmlsdGVyIENlbGxzIGJhc2VkIG9uIFFDIHBhcmFtZXRlcnMuCiMgNC4gQ3JlYXRlIGEgVGlsZU1hdHJpeCA1MDAtYnAgZ2Vub21lLXdpZGUuCiMgNS4gQ3JlYXRlIGEgR2VuZVNjb3JlTWF0cml4LgpBcnJvd0ZpbGVzIDwtIGNyZWF0ZUFycm93RmlsZXMoCiAgaW5wdXRGaWxlcyA9IGlucHV0RmlsZXMsCiAgc2FtcGxlTmFtZXMgPSBuYW1lcyhpbnB1dEZpbGVzKSwKICBnZW5lQW5ubyA9IGdlbmVBbm5vLAogIGdlbm9tZUFubm8gPSBnZW5vbWVBbm5vCikKYGBgCgojIFRpZHlpbmcgdXAgb3VyIGRhdGEgYW5kIGNyZWF0aW5nIGFuIGBBcmNoUlByb2plY3RgCgpPbmUgbWFqb3Igc291cmNlIG9mIHRyb3VibGUgaW4gc2luZ2xlLWNlbGwgZGF0YSBpcyB0aGUgY29udHJpYnV0aW9uIG9mICJkb3VibGV0cyIgdG8gdGhlIGFuYWx5c2lzLiBBIGRvdWJsZXQgcmVmZXJzIHRvIGEgc2luZ2xlIGRyb3BsZXQgdGhhdCByZWNlaXZlZCBhIHNpbmdsZSBiYXJjb2RlZCBiZWFkIGFuZCBtb3JlIHRoYW4gb25lIG51Y2xldXMuIFRoaXMgY2F1c2VzIHRoZSByZWFkcyBmcm9tIG1vcmUgdGhhbiBvbmUgY2VsbCB0byBhcHBlYXIgYXMgYSBzaW5nbGUgY2VsbC4gV2UgcmVtb3ZlIHRoZXNlIGNvbXB1dGF0aW9uYWxseSBhbmQgZGVzY3JpYmUgdGhpcyBkb3VibGV0IHJlbW92YWwgcHJvY2VzcyBpbiBtb3JlIGRlcHRoIGluIHRoZSBbZG91YmxldCByZW1vdmFsIHZpZ25ldHRlXShhcnRpY2xlcy9BcnRpY2xlcy9kb3VibGV0UmVtb3ZhbC5odG1sKS4KCmBgYHtyIGV2YWw9RkFMU0V9CiNBZGQgSW5mZXJlZCBEb3VibGV0IFNjb3JlcyB0byBlYWNoIEFycm93IEZpbGUgKH41LTEwIG1pbnV0ZXMpCmRvdWJTY29yZXMgPC0gYWRkRG91YmxldFNjb3JlcyhBcnJvd0ZpbGVzKQoKI0NyZWF0ZSBBcmNoUlByb2plY3QKI1RoZSBvdXRwdXREaXJlY3RvcnkgaGVyZSBkZXNjcmliZXMgd2hlcmUgYWxsIGRvd25zdHJlYW0gYW5hbHlzZXMgYW5kIHBsb3RzIGdvLgpwcm9qIDwtIEFyY2hSUHJvamVjdCgKICBBcnJvd0ZpbGVzID0gQXJyb3dGaWxlcywgCiAgZ2VuZUFubm90YXRpb24gPSBnZW5lQW5ubywKICBnZW5vbWVBbm5vdGF0aW9uID0gZ2Vub21lQW5ubywKICBvdXRwdXREaXJlY3RvcnkgPSAiSGVtZV9UdXRvcmlhbCIKKQoKI0ZpbHRlciBEb3VibGV0cwojVGhlIGF1dG9tYXRpYyBmaWx0ZXJpbmcgcmF0ZSB3aWxsIGJlIGJhc2VkIG9uIGhvdyBtYW55IGNlbGxzIGFyZSBpbiB0aGUgc2FtcGxlLCBpZiB0aGVyZQojYXJlIDUsMDAwIGNlbGxzIEFyY2hSIHdpbGwgcmVtb3ZlIHVwIHRvIDI1MCAofjUlKSBvZiB0aGUgY2VsbHMuIElmIHlvdSBiZWxpZXZlIG1vcmUgY2VsbHMKI3Nob3VsZCBiZSBleGNsdWRlZCBjaGFuZ2UgdGhlIGZpbHRlclJhdGlvIGFyZ3VtZW50IGFwcm9wcmlhdGVseS4KcHJvaiA8LSBmaWx0ZXJEb3VibGV0cyhwcm9qKQpgYGAKCiMgRGltZW5zaW9uYWxpdHkgUmVkdWN0aW9uIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKQXQgdGhpcyBwb2ludCwgd2UgaGF2ZSBhbiBBcmNoUiBwcm9qZWN0IHRoYXQgaXMgcmVhZHkgdG8gYmUgdXNlZCBpbiBkb3duc3RyZWFtIHZpc3VhbGl6YXRpb25zIGFuZCBhbmFseXNlcy4gVGhlIGZpcnN0IHRoaW5nIHdlIHdpbGwgZG8gaXMgdXNlIGFuIGl0ZXJhdGl2ZSBsYXRlbnQgc2VtYW50aWMgaW5kZXhpbmcgKExTSSkgYXBwcm9hY2ggdG8gZGVmaW5lIGNsdXN0ZXJzIGluIG91ciBkYXRhLiBPbmNlIHdlIGhhdmUgaWRlbnRpZmllZCBjbHVzdGVycyBpbiBvdXIgZGF0YSwgd2UgY2FuIHBsb3QgYSBVTUFQIGVtYmVkZGluZy4gRm9yIG1vcmUgZGV0YWlscywgc2VlIHRoZSBbZGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uIHZpZ25ldHRlXShhcnRpY2xlcy9BcnRpY2xlcy9kaW1SZWR1Y3Rpb24uaHRtbCkuCgpgYGB7ciBldmFsPUZBTFNFfQojUmVkdWNlIERpbWVuc2lvbnMgd2l0aCBJdGVyYXRpdmUgTFNJICh+NS0xMCBtaW51dGVzKQpwcm9qIDwtIGFkZEl0ZXJhdGl2ZUxTSSgKICBBcmNoUlByb2ogPSBwcm9qLCAKICB1c2VNYXRyaXggPSAiVGlsZU1hdHJpeCIsIAogIHJlZHVjZWREaW1zT3V0ID0gIkl0ZXJhdGl2ZUxTSSIKKQoKI0lkZW50aWZ5IENsdXN0ZXJzIGZyb20gSXRlcmF0aXZlIExTSQojVGhlIGxhcmdlciB0aGUgcmVzb2x1dGlvbiB0aGUgbW9yZSBjbHVzdGVycyB3aWxsIGJlIGNhbGxlZC4gVGhlIGxvd2VyIHRoZSByZXNvbHV0aW9uIGh0ZSBsZXNzIGNsdXN0ZXJzIHdpbGwgYmUgY2FsbGVkLgojSXQgaXMgcmVjb21tZW5kZWQgdG8gY29tcGFyZSB0aGUgcmVzdWx0cyBmcm9tIHlvdXIgY2x1c3RlcnMgYW5kIHlvdXIgZW1iZWRkaW5ncyBhbmQgZmluZCBwYXJhbXMgdGhhdCBiZXN0IGFncmVlIGFjcm9zcwojYm90aCBhbmFseXNlcyBmb3IgY2xhcml0eS4KcHJvaiA8LSBhZGRDbHVzdGVycyhpbnB1dCA9IHByb2osIHJlZHVjZWREaW1zID0gIkl0ZXJhdGl2ZUxTSSIsIHJlc29sdXRpb24gPSAwLjYpCgojQWRkIEltcHV0YXRpb24gV2VpZ2h0cyBmb3IgaW1wdXRpbmcgbnVtZXJpY2FsIHZhbHVlcyBiYXNlZCBvbiBNYWdpYyAoc2VlIHZhbiBEaWprIGV0LiBhbC4gMjAxOCkuCnByb2ogPC0gYWRkSW1wdXRlV2VpZ2h0cyhBcmNoUlByb2ogPSBwcm9qKQoKI0NvbXB1dGUgYSBVTUFQIGVtYmVkZGluZyB0byB2aXN1YWxpemUgb3VyIHRpbGVkIGFjY2Vzc2liaWxpdHkgbWF0cml4IGluIGEgMi1kIHNldHRpbmcuCnByb2ogPC0gYWRkRW1iZWRkaW5nKAogIEFyY2hSUHJvaiA9IHByb2osIAogIHJlZHVjZWREaW1zID0gIkl0ZXJhdGl2ZUxTSSIsIAogIGVtYmVkZGluZyA9ICJVTUFQIiwgCiAgZW1iZWRkaW5nUGFyYW1zID0gbGlzdChtaW5fZGlzdCA9IDAuNCksCiAgZm9yY2UgPSBUUlVFCikKCiNQbG90IHRoZSBVTUFQIEVtYmVkZGluZyB3aXRoIE1ldGFkYXRhIE92ZXJsYXllZCBzdWNoIGFzIEV4cGVyaW1lbnRhbCBTYW1wbGUgYW5kIENsdXN0ZXJzLgojVG8gY2hhbmdlIHBsb3R0aW5nIGFlc3RoZXRpY3Mgc2VlID9wbG90RW1iZWRkaW5nIHBhcmFtZXRlcnMuCnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFtbMV1dIDwtIHBsb3RFbWJlZGRpbmcoQXJjaFJQcm9qID0gcHJvaiwgY29sb3JCeSA9ICJjb2xEYXRhIiwgbmFtZSA9ICJTYW1wbGUiKQpwbG90TGlzdFtbMl1dIDwtIHBsb3RFbWJlZGRpbmcoQXJjaFJQcm9qID0gcHJvaiwgY29sb3JCeSA9ICJjb2xEYXRhIiwgbmFtZSA9ICJDbHVzdGVycyIsIHBsb3RQYXJhbXMgPSBsaXN0KGxhYmVsTWVhbnM9VFJVRSkpCnBsb3RQREYocGxvdExpc3QgPSBwbG90TGlzdCwgbmFtZSA9ICJVTUFQLVNhbXBsZXMtQ2x1c3RlcnMiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDYsIEFyY2hSUHJvaiA9IHByb2opCmBgYAoKKioqCgojIyBVTUFQIHcvIENsdXN0ZXJzClRoaXMgW3Bsb3RdKC4uLy4uL2ltYWdlcy90dXRvcmlhbF8xX1VNQVAtQ2x1c3RlcnMucGRmKSBzaG93cyBnZW5lIGV4cGVyaW1lbnRhbCBzYW1wbGVzIGFuZCBjbHVzdGVycyBkZXNjcmliZWQgYWJvdmUgb3ZlcmxheWVkIG9udG8gdGhlIFVNQVAgZW1iZWRkaW5nLiAoTm90ZSBpZiB5b3Ugc2VlIGEgYmxhbmsgc3BhY2UgYmVsb3cgdHJ5IGZpcmVmb3ggb3Igc2FmYXJpKTxici8+PGJyLz4KPGNlbnRlcj4KIVtBbHRdKC4uLy4uL2ltYWdlcy90dXRvcmlhbF8xX1VNQVAtQ2x1c3RlcnMucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTQ1MH0KPGNlbnRlcj4KCiMjIFVNQVAgdy8gQ3VzdG9tIENvbERhdGEKVG8gYWRkIHlvdXIgb3duIGluZm9ybWF0aW9uIGZvciBwbG90dGluZyBvbnRvcCBvZiBVTUFQIGVtYmVkZGluZyB3ZSB3aWxsIHNob3cgYW4gZXhhbXBsZSBoZXJlLgoKYGBge3IgZXZhbD1GQUxTRX0KCnByb2ogPC0gYWRkQ2VsbENvbERhdGEoQXJjaFJQcm9qID0gcHJvaiwgZGF0YSA9ICwgY2VsbE5hbWVzID0gKQoKI1Bsb3QgdGhlIFVNQVAgRW1iZWRkaW5nIHdpdGggTWV0YWRhdGEgT3ZlcmxheWVkIHN1Y2ggYXMgRXhwZXJpbWVudGFsIFNhbXBsZSBhbmQgQ2x1c3RlcnMuCiNUbyBjaGFuZ2UgcGxvdHRpbmcgYWVzdGhldGljcyBzZWUgP3Bsb3RFbWJlZGRpbmcgcGFyYW1ldGVycy4KcGxvdExpc3QgPC0gbGlzdCgpCnBsb3RMaXN0W1sxXV0gPC0gcGxvdEVtYmVkZGluZyhBcmNoUlByb2ogPSBwcm9qLCBjb2xvckJ5ID0gImNvbERhdGEiLCBuYW1lID0gIlNhbXBsZSIpCnBsb3RMaXN0W1syXV0gPC0gcGxvdEVtYmVkZGluZyhBcmNoUlByb2ogPSBwcm9qLCBjb2xvckJ5ID0gImNvbERhdGEiLCBuYW1lID0gIkNsdXN0ZXJzIiwgcGxvdFBhcmFtcyA9IGxpc3QobGFiZWxNZWFucz1UUlVFKSkKcGxvdFBERihwbG90TGlzdCA9IHBsb3RMaXN0LCBuYW1lID0gIlVNQVAtU2FtcGxlcy1DbHVzdGVycyIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNiwgQXJjaFJQcm9qID0gcHJvaikKCmBgYAoKIyBJZGVudGlmeWluZyBDbHVzdGVyIENlbGwgVHlwZXMgVXNpbmcgTWFya2VyIEdlbmVzIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKSW4gb3JkZXIgdG8gdW5kZXJzdGFuZCB3aGljaCBjbHVzdGVycyBjb3JyZXNwb25kIHRvIHdoaWNoIGNlbGwgdHlwZXMsIHdlIHVzZSBhIHN1cGVydmlzZWQgYXBwcm9hY2ggYmFzZWQgb24gcHJpb3Iga25vd2xlZGdlIG9mIHRoZSBnZW5lcyB0aGF0IGFyZSBhY3RpdmUgaW4gc3BlY2lmaWMgY2VsbCB0eXBlcy4gV2UgZGV0ZXJtaW5lIF9nZW5lIGFjdGl2aXR5IHNjb3Jlc18gZm9yIGVhY2ggcHV0YXRpdmUgbWFya2VyIGdlbmUgYmFzZWQgb24gY2hyb21hdGluIGFjY2Vzc2liaWxpdHkgc2lnbmFsIGluIHRoZSByZWdpb24gc3Vycm91bmRpbmcgdGhlIGdlbmUncyBwcm9tb3Rlci4gV2UgY2FuIHRoZW4gb3ZlcmxheSB0aGVzZSBfZ2VuZSBhY3Rpdml0eSBzY29yZXNfIG9uIG91ciBVTUFQIGVtYmVkZGluZyB0byB2aXN1YWxpemUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGdlbmUgYWN0aXZpdHkgYW5kIGNsdXN0ZXIuIEZvciBtb3JlIGRldGFpbHMsIHNlZSB0aGUgW21hcmtlciBnZW5lcyB2aWduZXR0ZV0oYXJ0aWNsZXMvQXJ0aWNsZXMvZ2VuZVNjb3Jlcy5odG1sKS4KCmBgYHtyIGV2YWw9RkFMU0V9Cm1hcmtlckdlbmVzICA8LSBjKAogICAgIkNEMzQiLCAjRWFybHkgUHJvZ2VuaXRvcgogICAgIkdBVEExIiwgI0VyeXRocm9pZAogICAgIlBBWDUiLCAiTVM0QTEiLCAjQi1DZWxsIFRyYWplY3RvcnkKICAgICJDRDE0IiwgI01vbm9jeXRlcwogICAgIkNEM0QiLCAiQ0Q4QSIsICJUQlgyMSIsICJJTDdSIiAjVENlbGxzCiAgKQoKI1Bsb3QgdGhlIFVNQVAgRW1iZWRkaW5nIHdpdGggTWFya2VyIEdlbmVzIE92ZXJsYXllZApwbG90TGlzdCA8LSBsaXN0KCkKcGxvdExpc3RbWzFdXSA8LSBwbG90RW1iZWRkaW5nKEFyY2hSUHJvaiA9IHByb2osIGNvbG9yQnkgPSAiR2VuZVNjb3JlTWF0cml4IiwgbmFtZSA9IG1hcmtlckdlbmVzKQpwbG90UERGKHBsb3RMaXN0ID0gcGxvdExpc3QsIG5hbWUgPSAiVU1BUC1NYXJrZXItR2VuZS1TY29yZXMiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDYsIEFyY2hSUHJvaiA9IHByb2opCgojUGxvdCBUcmFja3MgYXQgTWFya2VyIEdlbmVzCnBsb3RUcmFja3MgPC0gQXJjaFJSZWdpb25UcmFjayhBcmNoUlByb2ogPSBwcm9qLCB0aHJlYWRzID0gdGhyZWFkcywgZ2VuZVN5bWJvbCA9IG1hcmtlckdlbmVzKQpwbG90UERGKHBsb3RMaXN0ID0gcGxvdFRyYWNrcywgbmFtZSA9ICJUcmFja3MtTWFya2VyLUdlbmVzIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA4LCBBcmNoUlByb2ogPSBwcm9qKQoKI0lkZW50aWZ5IE1hcmtlciBHZW5lIHRocm91Z2ggUGFpcndpc2UgVGVzdCB2cyBOdWxsCm1hcmtlcnNHUyA8LSBtYXJrZXJGZWF0dXJlcyhBcmNoUlByb2ogPSBwcm9qLCB0aHJlYWRzID0gdGhyZWFkcywgdXNlTWF0cml4ID0gIkdlbmVTY29yZU1hdHJpeCIpCmhlYXRtYXBHUyA8LSBtYXJrZXJIZWF0bWFwKAogIHNlTWFya2VyID0gbWFya2Vyc0dTLCAKICBjdXRPZmYgPSAiRkRSIDw9IDAuMDEgJiBMb2cyRkMgPj0gMSIsIAogIGxhYmVsTWFya2VycyA9IG1hcmtlckdlbmVzCikKcGxvdFBERihoZWF0bWFwR1MsIG5hbWUgPSAiR1MtTWFya2VyLUhlYXRtYXAiLCB3aWR0aCA9IDgsIGhlaWdodCA9IDEyLCBBcmNoUlByb2ogPSBwcm9qKQpgYGAKCioqKgoKIyMgVU1BUCBHZW5lU2NvcmVzClRoaXMgW3Bsb3RdKC4uLy4uL2ltYWdlcy90dXRvcmlhbF8zX01hcmtlckdlbmVTY29yZXMucGRmKSBzaG93cyBnZW5lIGFjdGl2aXR5IHNjb3JlcyBvZiB0aGUgbWFya2VyIGdlbmVzIGRlc2NyaWJlZCBhYm92ZSBvdmVybGF5ZWQgb250byB0aGUgVU1BUCBlbWJlZGRpbmcuIFRoZSBnZW5lIHNjb3JlcyBhcmUgaW1wdXRlZCB1c2luZyBNYWdpYyB3aGVuIHJ1bm5pbmcgYWRkSW11cHRlV2VpZ2h0cy4gKE5vdGUgaWYgeW91IHNlZSBhIGJsYW5rIHNwYWNlIGJlbG93IHRyeSBmaXJlZm94IG9yIHNhZmFyaSk8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvdHV0b3JpYWxfM19NYXJrZXJHZW5lU2NvcmVzLnBkZil7d2lkdGg9NDUwIGhlaWdodD00NTB9CjxjZW50ZXI+CgojIyBUcmFjay1QbG90cwo8YnIvPjxici8+CjxjZW50ZXI+CiFbQWx0XSguLi8uLi9pbWFnZXMvdHV0b3JpYWxfMl90cmFja3MucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTYwMH0KPGNlbnRlcj4KCiMjIE1hcmtlciBHZW5lU2NvcmVzIEhlYXRtYXAKPGJyLz48YnIvPgo8Y2VudGVyPgohW0FsdF0oLi4vLi4vaW1hZ2VzL3R1dG9yaWFsXzRfTWFya2VyR2VuZUhlYXRtYXAucGRmKXt3aWR0aD00NTAgaGVpZ2h0PTYwMH0KPGNlbnRlcj4KCiMgQ3JlYXRpbmcgYSBSZXByb2R1Y2libGUgUGVhayBTZXQgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpPbmUgb2YgdGhlIG1vc3QgY29tcGxpY2F0ZWQgYXNwZWN0cyBhYm91dCBBVEFDLXNlcSBhbmQgc2NBVEFDLXNlcSBhbmFseXNpcyBpcyB0aGUgZ2VuZXJhdGlvbiBvZiBhIHJlcHJvZHVjaWJsZSBhbmQgcm9idXN0IHBlYWsgc2V0LiBJbiBBcmNoUiwgd2UgdXNlIGFuIGl0ZXJhdGl2ZSBvdmVybGFwIHJlbW92YWwgcHJvY2VzcyB0aGF0IHdlIGZpcnN0IGRlc2NyaWJlZCBpbiBbQ29yY2VzKiAmIEdyYW5qYSogZXQgYWwuIFNjaWVuY2UgMjAxOF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzAzNjEzNDEpLiBUaGlzIHByb2Nlc3MgaXMgZGVzY3JpYmVkIGluIGRldGFpbCBpbiB0aGUgW3BlYWsgY2FsbGluZyB2aWduZXR0ZV0oYXJ0aWNsZXMvQXJ0aWNsZXMvcGVha0NhbGxpbmcuaHRtbCkuCgpUbyByb2J1c3RseSBjYWxsIHBlYWtzLCB3ZSBmaXJzdCBtZXJnZSB0aGUgc3BhcnNlIHNpbmdsZS1jZWxsIGRhdGEgaW50byBwc2V1ZG8tYnVsayByZXBsaWNhdGVzIGJ5IGFnZ3JlZ2F0aW5nIHRoZSBpbnNlcnRpb25zIGZyb20gbWFueSBpbmRpdmlkdWFsIGNlbGxzIGludG8gYSBzaW5nbGUgZ3JvdXAuIFdlIG1ha2UgbXVsdGlwbGUgcHNldWRvLWJ1bGsgcmVwbGljYXRlcyBmb3IgZWFjaCBjbHVzdGVyIHRvIGVuYWJsZSBhbiBhc3Nlc3NtZW50IG9mIHBlYWsgcmVwcm9kdWNpYmlsaXR5LiBUaGlzIHByb2Nlc3Mgb2YgcHNldWRvLWJ1bGsgZ2VuZXJhdGlvbiBpcyBkZXNjcmliZWQgaW4gZGV0YWlsIGluIHRoZSBbcHNldWRvLWJ1bGsgZ2VuZXJhdGlvbiB2aWduZXR0ZV0oYXJ0aWNsZXMvQXJ0aWNsZXMvcHNldWRvYnVsa0dlbmVyYXRpb24uaHRtbCkuIFdlIHRoYW4gY2FsbCBwZWFrcyB1c2luZyBbTUFDUzJdKGh0dHBzOi8vZ2l0aHViLmNvbS90YW9saXUvTUFDUykgYW5kIHBlcmZvcm0gb3VyIGl0ZXJhdGl2ZSBvdmVybGFwIHJlbW92YWwuIE9uY2Ugd2Ugb2J0YWluIGEgZmluYWxpemVkIHBlYWsgc2V0LCB3ZSBjb2xsZWN0IGluc2VydGlvbiBjb3VudHMgaW4gZWFjaCBwZWFrIGZvciBlYWNoIHNpbmdsZSBjZWxsIGFuZCBhc3NvY2lhdGUgdGhpcyB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIGBBcnJvd0ZpbGVgIHZpYSB0aGUgYEFyY2hSUHJvamVjdGAuCgpgYGB7ciBldmFsPUZBTFNFfQojQ3JlYXRlIEdyb3VwIENvdmVyYWdlIEZpbGVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGRvd25zdHJlYW0gYW5hbHlzaXMgKH41LTEwIG1pbnV0ZXMpCnByb2ogPC0gYWRkR3JvdXBDb3ZlcmFnZXMoQXJjaFJQcm9qID0gcHJvaiwgZ3JvdXBCeSA9ICJDbHVzdGVycyIsIHRocmVhZHMgPSB0aHJlYWRzKQoKI0NhbGwgUmVwcm9kdWNpYmxlIFBlYWtzIHcvIE1hY3MyICh+NS0xMCBtaW51dGVzKQpwcm9qIDwtIGFkZFJlcHJvZHVjaWJsZVBlYWtTZXQoQXJjaFJQcm9qID0gcHJvaiwgZ3JvdXBCeSA9ICJDbHVzdGVycyIsIHRocmVhZHMgPSB0aHJlYWRzKQoKI0FkZCBQZWFrIE1hdHJpeApwcm9qIDwtIGFkZFBlYWtNYXRyaXgoQXJjaFJQcm9qID0gcHJvaiwgdGhyZWFkcyA9IHRocmVhZHMsIGZvcmNlID0gVFJVRSkKYGBgCgojIElkZW50aWZ5aW5nIE1hcmtlciBQZWFrcwoKT2Z0ZW4gdGltZXMsIHdlIGFyZSBpbnRlcmVzdGVkIHRvIGtub3cgd2hpY2ggcGVha3MgYXJlIHVuaXF1ZSB0byBhbiBpbmRpdmlkdWFsIGNsdXN0ZXIgb3IgYSBzbWFsbCBncm91cCBvZiBjbHVzdGVycy4gV2UgY2FuIGRvIHRoaXMgaW4gYW4gdW5zdXBlcnZpc2VkIGZhc2hpb24gaW4gQXJjaFI6CgpgYGB7ciBldmFsPUZBTFNFfQojSWRlbnRpZnkgTWFya2VyIFBlYWtzCm1hcmtlcnNQZWFrcyA8LSBtYXJrZXJGZWF0dXJlcyhBcmNoUlByb2ogPSBwcm9qLCB0aHJlYWRzID0gdGhyZWFkcywgdXNlTWF0cml4ID0gIlBlYWtNYXRyaXgiKQpoZWF0bWFwUGVha3MgPC0gbWFya2VySGVhdG1hcCgKICBzZU1hcmtlciA9IG1hcmtlcnNQZWFrcywgCiAgY3V0T2ZmID0gIkZEUiA8PSAwLjAxICYgTG9nMkZDID49IDEiCikKcGxvdFBERihoZWF0bWFwUGVha3MsIG5hbWUgPSAiUGVhay1NYXJrZXItSGVhdG1hcCIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gMTIsIEFyY2hSUHJvaiA9IHByb2opCmBgYAoKVXNpbmcgb3VyIHR1dG9yaWFsIGRhdGEsIHlvdXIgbWFya2VyIHBlYWsgaGVhdG1hcCBzaG91bGQgbG9vayBsaWtlIFt0aGlzXShhcnRpY2xlcy9BcnRpY2xlcy9UdXRvcmlhbF9tYXJrZXJQZWFrc19IRUFUTUFQLnBkZikuCgojIFBlcmZvcm1pbmcgTW90aWYgRW5yaWNobWVudHMKClFRUVFRUVEgLSBJIHRoaW5rIHRoZSBjb25jZXB0IG9mIFRGIGRldmlhdGlvbnMgaXMgc3RpbGwgYWJzdHJhY3QgdG8gbW9zdCBwZW9wbGUuIERvZXMgQXJjaFIgZG8gbW90aWYgZW5yaWNobWVudCB3aXRoIGh5cGVyZ2VvbWV0cmljIHRlc3QgYXMgd2VsbD8/CgpVc2luZyB0aGUgcmVwcm9kdWNpYmxlIHBlYWsgc2V0IHRoYXQgd2UgZGVmaW5lZCBhYm92ZSwgd2UgY2FuIHVzZSBBcmNoUiB0byBjYWxjdWxhdGUgVEYgZGV2aWF0aW9ucyBvbiBhIHNpbmdsZS1jZWxsIGJhc2lzIGZvciB0cmFuc2NyaXB0aW9uIGZhY3RvcnMgaW4gdGhlIHBlYWtzIGlkZW50aWZpZWQgaW4gZWFjaCBjbHVzdGVyLiBXZSBjYW4gdGhlbiBvdmVybGF5IHRoZXNlIGRldmlhdGlvbnMgb24gb24gVU1BUCBlbWJlZGRpbmcuIFRoaXMgZWZmZWN0aXZlbHkgaW5mZXJzIGRpZmZlcmVuY2VzIGluIFRGIGFjdGl2aXR5IGFjcm9zcyBhbGwgc2luZ2xlIGNlbGxzIGFuZCBpcyB2ZXJ5IHVzZWZ1bCBpbiBpZGVudGlmeWluZyByZWd1bGF0b3J5IGZhY3RvcnMgZ292ZXJuaW5nIGNlbGwgZmF0ZS4KCmBgYHtyIGV2YWw9RkFMU0V9CiNNb3RpZiBTZWFyY2ggaW4gUGVha1NldApwcm9qIDwtIGFkZE1vdGlmQW5ub3RhdGlvbnMoQXJjaFJQcm9qID0gcHJvaiwgbmFtZSA9ICJNb3RpZiIpCgojQWRkIGNocm9tVkFSIERldmlhdGlvbnMgKH4yMC0yNSBtaW4gaWYgdXNpbmcgQ2lzQlAgTW90aWZTZXQpCnByb2ogPC0gYWRkRGV2aWF0aW9uc01hdHJpeChBcmNoUlByb2ogPSBwcm9qLCB0aHJlYWRzID0gdGhyZWFkcykKCiNJZGVudGlmeSBWYXJpYWJsZSBURnMKaGVhZChnZXRWYXJEZXZpYXRpb25zKHByb2osIHBsb3QgPSBGQUxTRSkkbmFtZSwgMjUpCgojVG8gYWNjZXNzIG1vdGlmIG5lZWQgdG8gc3BlY2lmeSBkZXZpYXRpb25zLHogOiBtb3RpZl9uYW1lCiNUcnkgZ2V0RmVhdHVyZXMgd2l0aCBNb3RpZk1hdHJpeCB0byBzZWUgYXZhaWxhYmxlIG5hbWVzCmdldEZlYXR1cmVzKHByb2osIHNlbGVjdCA9ICJQQVg1IiwgdXNlTWF0cml4ID0gIk1vdGlmTWF0cml4IikKCiNEZWZpbmUgdGhlIGxpc3Qgb2YgbW90aWZzIHRvIHBsb3QKbW90aWZzIDwtIGMoIkdBVEExXzM4MyIsICJDRUJQQV8xNTUiLCAiRUJGMV82NyIsIklSRjRfNjMyIiwiVEJYMjFfNzgwIiwiUEFYNV83MDkiKQoKI1Bsb3QgdGhlIFVNQVAgRW1iZWRkaW5nIHdpdGggY2hyb21WQVIgRGV2aWF0aW9ucyBPdmVybGF5ZWQKcGxvdExpc3QgPC0gbGlzdCgpCnBsb3RMaXN0W1sxXV0gPC0gcGxvdEVtYmVkZGluZyhBcmNoUlByb2ogPSBwcm9qLCBjb2xvckJ5ID0gImNvbERhdGEiLCBuYW1lID0gIkNsdXN0ZXJzIikKcGxvdExpc3RbWzJdXSA8LSBwbG90RW1iZWRkaW5nKEFyY2hSUHJvaiA9IHByb2osIGNvbG9yQnkgPSAiTW90aWZNYXRyaXgiLCBuYW1lID0gcGFzdGUwKCJ6OiIsbW90aWZzKSkKcGxvdFBERihwbG90TGlzdCA9IHBsb3RMaXN0LCBuYW1lID0gIlBsb3QtVU1BUC1UaWxlTFNJLU1vdGlmTWF0cml4Iiwgd2lkdGggPSA2LCBoZWlnaHQgPSA2LCBBcmNoUlByb2ogPSBwcm9qKQpgYGAKClVzaW5nIG91ciB0dXRvcmlhbCBkYXRhLCB5b3VyIG1hcmtlciBwZWFrIGhlYXRtYXAgc2hvdWxkIGxvb2sgbGlrZSBbdGhpc10oYXJ0aWNsZXMvQXJ0aWNsZXMvVHV0b3JpYWxfbW90aWZFbnJpY2htZW50X1VNQVAucGRmKS4KCiMgUGVyZm9ybWluZyBURiBGb290cHJpbnRpbmcKClRyYW5zY3JpcHRpb24gZmFjdG9yIGZvb3RwcmludGluZyBjYW4gYWxzbyBiZSBkb25lIGluIEFyY2hSIHdpdGggYSBzaW5nbGUgY29tbWFuZC4gV2Ugbm90ZSB0aGF0IHRoZSBmb290cHJpbnRzIGdlbmVyYXRlZCBieSB0aGUgdHV0b3JpYWwgZGF0YSBhcmUgbm90IGFzIGNsZWFuIGFzIHdvdWxkIGJlIGRlc2lyZWQgYnV0IHRoaXMgaXMgYmVjYXVzZSBvZiB0aGUgc21hbGwgc2l6ZSBvZiB0aGUgdHV0b3JpYWwgZGF0YXNldC4KCmBgYHtyIGV2YWw9RkFMU0V9CiNQbG90IE1vdGlmIEZvb3RwcmludHMgZnJvbSBwb3NpdGlvbnMgbGlzdAojUmVjb21tZW5kIGRvaW5nIGEgZmV3IG1vdGlmcyBub3QgZW50aXJlIG1vdGlmIHNldApzZUZvb3QgPC0gcGxvdEZvb3RwcmludHMocHJvaiwgcG9zaXRpb25zID0gZ2V0UG9zaXRpb25zKHByb2opW21vdGlmc10pCmBgYAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK